package org.misty.practices.algorithm.hanoi.normal;


import java.util.ArrayList;
import java.util.List;

public class Hanoi {
    private List<String> steps;
    private Tower a;
    private Tower b;
    private Tower c;

    public Hanoi(int level) {
        reset(level);
    }

    public void reset(int level) {
        if (level <= 0) {
            throw new IllegalArgumentException("层数必须大于0");
        }
        this.steps = new ArrayList<>();
        this.a = new Tower("a", level);
        this.b = new Tower("b");
        this.c = new Tower("c");
        if (level % 2 == 0) { // 层数为偶数，顺时针移动
            a.setNext(b);
            b.setNext(c);
            c.setNext(a);
        } else { // 层数为奇数，逆时针移动
            a.setNext(c);
            c.setNext(b);
            b.setNext(a);
        }
    }

    public void start() {
        var mvp = this.a;
        if (mvp.isEmpty()) return;
        Tower x;
        Tower y;
        while (true) {
            steps.add(mvp.moveToNext()); // 最小盘移动到下个塔

            mvp = mvp.getNext(); // 保持对最小盘所在塔的引用
            x = mvp.getNext();
            y = x.getNext();

            if (x.isEmpty() && y.isEmpty()) break;
            /*
             * 剩下两个塔中
             * 1. 如果有一个空塔，则移动非空塔的顶盘到空塔
             * 2. 移动较小的顶盘到另一个塔
             */
            steps.add(Tower.exchange(x, y));
        }
    }

    public void printSteps() {
        if (steps != null && !steps.isEmpty()) {
            for (var step : steps) {
                System.out.println(step);
            }
        }
    }

    public static void main(String[] args) {
        var hanoi = new Hanoi(5);
        hanoi.start();
        hanoi.printSteps();
    }
}
/* 2
a -> b
a -> c
b -> c
 */
/* 3
a -> c
a -> b
c -> b
a -> c
b -> a
b -> c
a -> c
 */
/* 4
a -> b
a -> c
b -> c
a -> b
c -> a
c -> b
a -> b
a -> c
b -> c
b -> a
c -> a
b -> c
a -> b
a -> c
b -> c
 */
/* 5
a -> c
a -> b
c -> b
a -> c
b -> a
b -> c
a -> c
a -> b
c -> b
c -> a
b -> a
c -> b
a -> c
a -> b
c -> b
a -> c
b -> a
b -> c
a -> c
b -> a
c -> b
c -> a
b -> a
b -> c
a -> c
a -> b
c -> b
a -> c
b -> a
b -> c
a -> c
 */
